package com.haipumi.webSocket;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.apache.struts2.ServletActionContext;
import org.hyperic.sigar.CpuInfo;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.context.support.WebApplicationObjectSupport;

import com.google.gson.Gson;
import com.haipumi.beans.HardDisk;
import com.haipumi.beans.ServiceInfo;
import com.haipumi.utils.CommonData;
import com.haipumi.utils.LogUtil;
import com.opensymphony.xwork2.ActionContext;

@ServerEndpoint("/backadmin/ServiceInfo")
public class ServiceInfos  extends WebApplicationObjectSupport{
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //用于初次连接时的临时ID
    private static int TEMPID = 0;
    
    static boolean  flag=false;
    
    ServiceInfo si=new ServiceInfo();
    
    private ServletContext servletContext;
     
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    private static Map<String,ServiceInfos > webSocketMap = new Hashtable<String, ServiceInfos >();
    //用于将临时Id与用户Id联系起来
    private static Map<String,String> tempRelation=new Hashtable<String,String>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    
    //当前用户的ID
    private String UserId;
    //临时ID标记,因为刚建立连接的时候,并不能得到用户的id
    private String tempId;
    
     
    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     * @throws IOException 
     * @throws SigarException 
     */
    @OnOpen
    public void onOpen(Session session) throws IOException, SigarException{
        this.session = session;
        tempId=getTEMPID();
        webSocketMap.put( tempId, this);
        addOnlineCount();           //在线数加1
        LogUtil.log.debug("有新连接加入！当前在线人数为" + getOnlineCount());
        System.out.println("临时Id:  "+tempId);
        
        flag=true;
        sendMessage();
    }
     
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
    	webSocketMap.remove(tempId);  //从set中删除
        subOnlineCount();           //在线数减1    
        LogUtil.log.debug("有一连接关闭！当前在线人数为" + getOnlineCount());
        flag=false;
    }
     
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
//    	System.out.println("来自客户端的消息:"+message);
//    	//传来的消息格式    发送人ID,接收人ID-MESSAGE
//    	int textIndex=message.indexOf("-");
//    	String UsersId=message.substring(0, textIndex );//获取用户ID的字符串
//    	String text=message.substring(textIndex+1);//获取消息的字符串
//
//    	String[] UsersIds=UsersId.split(",");
//    	UserId=UsersIds[0];
//    	String friendId=UsersIds[1];
//    	
//    	
//    	if(!tempRelation.containsKey(UserId)){//如果联系关系集合中没有该用户id,则建立起联系
//    		tempRelation.put(UserId, tempId);
//    	}
//    	
//    	if(tempRelation.containsKey(friendId)){//取出聊天对方的session,并发送消息
//    		ServiceInfo task=webSocketMap.get(tempRelation.get(friendId));
//    		task.session.getAsyncRemote().sendText(text);
//    	}
    	
//    	
//        for (Session sess : session.getOpenSessions()) {
//		   if (sess.isOpen()){
//			   sess.getAsyncRemote().sendText(message);
//		   }
//		}
    }
     
    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
    	LogUtil.log.fatal("查询任务总数websocket 发生错误");
        error.printStackTrace();
    }
     
    /**
     * 这个方法与上面几个方法不一样。没有用注解，是根据自己需要添加的方法。
     * @param message
     * @throws IOException
     * @throws SigarException 
     */
    public void sendMessage() throws IOException, SigarException{
//        this.session.getBasicRemote().sendText(message);//阻塞
        do{
//        	ActionContext ac = ActionContext.getContext();
//        	HttpServletRequest request =(HttpServletRequest)ac.get(ServletActionContext.HTTP_REQUEST);
//        	HttpServletRequest response =(HttpServletRequest)ac.get(ServletActionContext.HTTP_RESPONSE);
        	
        	property();
			// cpu信息
			cpu();
			// 内存信息
			memory();
			// 操作系统信息
			os();
			// 文件系统信息
			file();
			Gson gson=new Gson();
			
        	String message=gson.toJson(si);
        	this.session.getAsyncRemote().sendText(message);//非阻塞
        	try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }while(flag=true);
    }
    
    
    private void file() throws SigarException {
    	Sigar sigar = new Sigar();
        FileSystem fslist[] = sigar.getFileSystemList();
        //TODO 有bug fslist.length 长度为5  单实际所需要的长度为4
        
        List<HardDisk> hdlist=new ArrayList<HardDisk>();
//        for (int i = 0; i < fslist.length; i++) {
        for (int i = 0; i < 1; i++) {
        	HardDisk hd=new HardDisk();
        	//out.println("分区的盘符名称" + i);
        	
            FileSystem fs = fslist[i];
            // 分区的盘符名称
            //out.println("盘符名称:   " + fs.getDevName()+"<br/>");
            hd.setName(fs.getDevName());
            // 分区的盘符名称
            //out.println("盘符路径:   " + fs.getDirName()+"<br/>");
            //out.println("盘符标志:   " + fs.getFlags()+"<br/>");//
            // 文件系统类型，比如 FAT32、NTFS
            //out.println("盘符类型:   " + fs.getSysTypeName()+"<br/>");
           	hd.setSystypename(fs.getSysTypeName());
            // 文件系统类型名，比如本地硬盘、光驱、网络文件系统等
            //out.println("盘符类型名:  " + fs.getTypeName()+"<br/>");
            hd.setType(fs.getTypeName());
            FileSystemUsage usage = null;
            usage = sigar.getFileSystemUsage(fs.getDirName());
            switch (fs.getType()) {
            case 0: // TYPE_UNKNOWN ：未知
                break;
            case 1: // TYPE_NONE
                break;
            case 2: // TYPE_LOCAL_DISK : 本地硬盘
                // 文件系统总大小
            	//out.println(fs.getDevName() + "总大小:  " + usage.getTotal()/(1048576) + "GB"+"<br/>");
                hd.setTotalsize(Long.toString(usage.getTotal()/(1048576)));
                // 文件系统已经使用量
            	//out.println(fs.getDevName() + "已经使用量:    " + usage.getUsed()/(1048576) + "GB"+"<br/>");
                hd.setUsedsize(Long.toString(usage.getUsed()/(1048576)));
                break;
            case 3:// TYPE_NETWORK ：网络
                break;
            case 4:// TYPE_RAM_DISK ：闪存
                break;
            case 5:// TYPE_CDROM ：光驱
                break;
            case 6:// TYPE_SWAP ：页面交换
                break;
            }
            double temp=(usage.getUsed()/(1048576))/(usage.getTotal()/(1048576));
            hd.setZhanyonglv(Integer.toString((int)(temp*100)));
            hdlist.add(hd);
        }
        si.setDisklist(hdlist);
        return;
	}

	private void os() {
		OperatingSystem OS = OperatingSystem.getInstance();
		// out.println("操作系统名称: " + OS.getVendorName()+"<br/>");
		si.setSystemname(OS.getVendorName());
		// 操作系统的版本号
		// out.println("操作系统的版本号:   " + OS.getVersion()+"<br/>");
		si.setSystemversion(OS.getVersion());
	}

	private void memory() throws SigarException {
		Sigar sigar = new Sigar();
		Mem mem = sigar.getMem();
		// 内存总量
		// out.println("内存总量:   " + mem.getTotal() / 1024L + "K av"+"<br/>");
		si.setRomtotal(Long.toString(mem.getTotal()));
		// 当前内存使用量
		// out.println("当前内存使用量:    " + mem.getUsed() / 1024L +
		// "K used"+"<br/>");
		si.setRomuse(Long.toString(mem.getUsed()));
	}

	private void cpu() throws SigarException {
		Sigar sigar = new Sigar();
		CpuInfo infos[] = sigar.getCpuInfoList();
		CpuPerc cpuList[] = null;
		cpuList = sigar.getCpuPercList();
		double temp = 0.0;
		for (int i = 0; i < 2; i++) {// 不管是单块CPU还是多CPU都适用
			CpuInfo info = infos[i];
			// out.println("CPU生产商: " + info.getVendor()+"<br/>");//
			// 获得CPU的卖主，如：Intel
			si.setCpumaker(info.getVendor());
			temp += printCpuPerc(cpuList[i], si, temp);
		}
		si.setCpuuse(Double.toString(temp / infos.length));
	}
	
	private double printCpuPerc(CpuPerc cpu, ServiceInfo si2, double temp) {
		temp+=cpu.getCombined();
    	return temp;
	}

	private void property() throws UnknownHostException {
    	Runtime r = Runtime.getRuntime();
		Properties props = System.getProperties();
		InetAddress addr;
		addr = InetAddress.getLocalHost();
		String ip = addr.getHostAddress();

		// out.println("本地ip地址: " + ip+"<br/>");
		si.setIp(ip);
		// out.println("本地主机名:  " + addr.getHostName()+"<br/>");
		si.setComputername(addr.getHostName());
		// out.println("JVM可以使用的处理器个数:  " + r.availableProcessors()+"<br/>");
		si.setCpunum(Integer.toString(r.availableProcessors()));
		// out.println("Java的运行环境版本：    " +
		// props.getProperty("java.version")+"<br/>");
		si.setJavaversion(props.getProperty("java.version"));
		// out.println("用户的当前工作目录：  " + props.getProperty("user.dir")+"<br/>");
		si.setUserdocument(props.getProperty("user.dir"));
	}

	//获取当前在线人数
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    //人数加1
    public static synchronized void addOnlineCount() {
        ServiceInfos.onlineCount++;
    }
    //人数减1
    public static synchronized void subOnlineCount() {
        ServiceInfos.onlineCount--;
    }

	public static synchronized String getTEMPID() {
		TEMPID++;
		return Integer.toString( TEMPID );
	}

	@Override
	protected void initServletContext(ServletContext servletContext) {
		this.servletContext=servletContext;
	}
    
}